\section{The SOS Environment}
\label{sec:The SOS Environment}

The following sections are addressed to the predefined types
supplied by SOS.
They are defined in the schemas {\tt knl}, {\tt agg}, {\tt dir},
and {\tt mta}.
The schema {\tt knl} contains a minimal kernel of types which are necessary
for any implementation;
{\tt agg} contains some predefined aggregate classes like e.g.
{\tt List} and {\tt Set} that facilitate the definition of
new (complex) classes and may be included by a user-defined schema.
The schema {\tt dir} provides a hierarchical directory
facility resembling the {\it UNIX} file system.
The schema {\tt mta} defines the meta types, that means the types for
the representation of types and their constituents, like e.g.
methods.

%----------
\subsection{The Kernel Types}

The schema {\tt knl} defines the following scalar types 
and classes:
\begin{verbatim}
extern void (0);

extern sos_Int (4);
extern sos_Char (1);
extern sos_Cstring (4);
extern sos_Pointer (4);

enum   sos_Bool {FALSE, TRUE};
enum   sos_Eq_kind {EQ_STRONG, EQ_WEAK};
enum   sos_Comp_result {CMP_LESS, CMP_EQUAL, CMP_GREATER};

extern sos_Container (4);
extern sos_Offset (4);
extern sos_Id (8);

class  sos_Object;
class  sos_Ordered_object;
class  sos_Scalar_object;
class  sos_Type;
class  sos_Named;
class  sos_String;
\end{verbatim}

The relationships between some of the kernel types 
are illustrated in Figure \ref{fig:KNL}.

\begin{figure}[hbt]
\begin{center}
\
\vspace*{7.5mm}
\psfig{figure=figures/knl.epsi,height=8cm,width=13cm}
\vspace*{7.5mm}
\end{center}
\caption{\label{fig:KNL}Inheritance relationships among predefined
         kernel classes.}
\end{figure}

The external types {\tt void}, {\tt sos\_Int}, {\tt sos\_Char}, 
{\tt sos\_Cstring}, and {\tt sos\_Pointer} as well
as the enumeration types  {\tt sos\_Bool}, {\tt sos\_Eq\_kind},
and  {\tt sos\_Comp\_result} 
are described in Section~\ref{sec:The Scalar Types}.

The class {\tt sos\_Object} is the (indirect) superclass of all classes,
whereas the class {\tt sos\_Scalar\_object} can be considered as
the implicit supertype of all scalar types
(see Section~\ref{sec:The Scalar Types}).
The classes {\tt sos\_Object}, {\tt sos\_Scalar\_object}, 
{\tt sos\_Ordered\_object}, {\tt sos\_Type}, {\tt sos\_Named},
and {\tt sos\_String}
are described in detail in Appendix~\ref{sec:Manual Pages}.

The type {\tt sos\_Container} plays a special role that will be
described in Section~\ref{sec:The Type sos_Container}.
The type {\tt sos\_Offset} denotes the position of an object within
a container; it is only used for internal purposes.
This holds also true for the type {\tt sos\_Id}.

%-------------
\subsubsection{The Scalar Types}
\label{sec:The Scalar Types}

Besides the types used for container management, that are
described separately in 
Section~\ref{sec:The Type sos_Container}, the following external and
enumeration types are declared in the schema {\tt knl}:
\begin{verbatim}
extern void (0);

extern sos_Int (4);
extern sos_Bool (1);
extern sos_Char (1);
extern sos_Cstring (4);
extern sos_Pointer (4);

enum   sos_Bool {FALSE, TRUE};
enum   sos_Eq_kind {EQ_STRONG, EQ_WEAK};
enum   sos_Comp_result {CMP_LESS, CMP_EQUAL, CMP_GREATER};
\end{verbatim}
The external type {\tt void} is a type with no value, it is used
to indicate functions returning nothing.

The type {\tt sos\_Int} represents integer numbers.
The numbers supported by the kernel are restricted to a length of
four bytes (whereby a two's-complement form is used).

The type {\tt sos\_Char} represents one-byte ASCII characters;
the type {\tt sos\_Cstring} is intended to hold a pointer to
a successive number of {\tt sos\_Char} objects, whose end is
indicated by the ASCII control character {\tt NUL}, whereas
the type {\tt sos\_Pointer} is intended to hold arbitrary pointers to 
main memory.%
\footnote{Note, that as well {\tt sos\_Cstring} as {\tt sos\_Pointer}
          should not be stored as persistent objects since their
          meaning is confined to a single process.}

The enumeration type {\tt sos\_Bool} represents the boolean truth values.
The enumeration type {\tt sos\_Eq\_kind} is presumably
mostly used as argument type in calls of the predefined method
{\tt equal} (see Section~\ref{sec:Comparing Objects}).
The remaining enumeration type {\tt sos\_Comp\_result} can be used as
the return value of comparison operations
(see e.g. {\tt sos\_Ordered\_object}).

Objects of the predefined scalar types and all enumeration types are
stored in the SOS system 
in an exactly defined, machine and language independent way.%
\footnote{All instances of SOS class types are of course also stored in a
          machine and language independent way.
          For the layout specification refer to the implementation
          description \cite{SOSI91}.}
They can be used by applications written in
different languages and running on different machines.

Scalar types are no class types, therefore no instances of a scalar
type can be created and no application specific function methods
can be defined for them.
Objects of scalar types lie on the boundary between SOS and a
host programming language. This is examplified by the fact that
there are two representations of these objects:
\begin{itemize}
\item A representation in the host language obtained by  mapping the
      scalar type to a type in the respective programming language.
      This representation can be manipulated as defined in the
      respective language.
\item An object representation which acts like an instance of a subtype
      of class {\tt sos\_Scalar\_object}, i.e. this representation can be
      used anywhere, where instances of {\tt sos\_Scalar\_object}
      may appear.%
      \footnote{In this sense {\tt sos\_Scalar\_object} is an indirect
                supertype of all scalar objects.}
\end{itemize}
Means for converting between both scalar object representations are defined
by the respective language binding. The conversion operations provided by
the C++ language binding are described in
Section~\ref{sec:External Types} and
Section~\ref{sec:Enumeration Types}.

%-------------
\subsubsection{The Type sos\_Container}
\label{sec:The Type sos_Container}

Containers provide a simple mechanism for synchronization, recovery,
and clustering of objects.
Each object of SOS belongs to exactly one container, which is
determined when an object is created.
Containers are handled similar to SOS objects;
however, {\tt sos\_Container} is not a SOS class but an external
type.%
\footnote{Nevertheless, most language bindings will provide a
          (host language) class {\tt sos\_Container} which can then
          be handled similar to the (host language) classes which
          are generated as interfaces for SOS class.}
Furthermore, a container object cannot be created within another
container, whereas all non-container objects must be created within
a container.
They are affiliated to that container throughout their lifetime. 
With the destruction of a container all objects that have been
created within this container will be destroyed%
\footnote{Note, that the destroy method will not be called for
          objects destroyed that way.}.

All operations that modify the value of an object require that
the corresponding container has explicitly been opened for writing.
An operation that reads the value of an object implicitly opens the
corresponding container for reading, if it has not yet been opened.

Although {\tt sos\_Container} is not a SOS class, some of its
operations can best be introduced in a SOS like class declaration:%
\footnote{A full description can be found in the corresponding
          manual pages contained in Appendix~\ref{sec:Manual Pages}.}
\begin{verbatim}
enum sos_Sync_mode {WAITING,TESTING};
enum sos_Open_result {OPENED,LOCKED,UNACCESSIBLE};
enum sos_Access_mode {READING,WRITING};
enum sos_Container_status {READABLE,WRITEABLE,UNAVAILABLE,DESTROYED};
enum sos_Existing_status {NOT_EXISTING, PERHAPS_EXISTING};

class sos_Container
{
public:

    static sos_Container create();

    sos_Container_status status();

    sos_Open_result open (sos_Access_mode, sos_Sync_mode);
    sos_Open_result access (sos_Access_mode, sos_Sync_mode);
    void close();
    void destroy();

    void commit();
    void reset();

    void clear();

    sos_Object root_object();
};
\end{verbatim}
The {\tt create} operation for containers differs from the
{\tt create} method for SOS classes because it has no parameter for
the container in which the new container shall be allocated.

The status of a container, i.e. whether it is closed, opened for
reading, or opened for writing, can be inspected by the {\tt status}
operation.

The {\tt open} operation opens the container for either reading or
writing, depending on the access mode parameter.

The (inter-process) synchronization strategy permits that a container
may be either opened several times for reading or once for writing.
A parameter specifies the desired reaction if the container cannot
be opened: the open operation may then either wait or return
immediately with an error code.
From the applications point of view, the sole purpose of opening a
container is synchronization.

When a container is opened with read permission, it can be upgraded
to write permission and vice versa using the {\tt access} operation.
The container must have been opened and the new access mode is given
by a parameter.
Calls to {\tt access} are synchronized in the same way as calls to
{\tt open}.

A {\tt close} operation on a container makes it accessible to
other processes according to the synchronization strategy.
Additionally, closing a container which is opened for writing implies
a {\tt commit} on this container.

Destruction of a container is accomplished by {\tt destroy}.
Destruction of a container requires exclusive access to it, i.e. the
container must be opened for writing. Like all other modifications 
on containers
the destroy operation must be committed to remove the container
persistently.

When a container is opened for writing, a (conceptual) copy of it is
made and all changes will be made to the copy.
The {\tt commit} operation replaces the original container by its
copy;
with {\tt reset} the changes made since the last commit operation
are ignored.
{\tt commit} and {\tt reset} must only be called on containers
opened for writing.

Furthermore, a container opened for writing may be emptied using the
{\tt clear} operation.
All objects created within the container are destroyed, but the
container itself continues to exist.

The function {\tt root\_object} returns the object that was
created as the first object in the container.
The root object is particularly suited for objects acting as an entry
point for a container from where other objects stored in the
container can be reached.
Note, that the association between a container and its root object
is fixed from the moment on when this object is created in the container,
and that this relation can never be changed.
In case that an object that was created as the root object of a
particular container is destroyed, the result of function {\tt root\_object}
is undefined.

There exist some dedicated containers which neither must be destroyed nor can be
created.
These are the {\it temporary container} (named {\tt TEMP\_CONTAINER})
and the {\it root container} (named {\tt ROOT\_CONTAINER}).
Each process has its own temporary container.
The contents of a temporary container will be deleted when its
associated process terminates, i.e. it is non-persistent.
However, compared to persistent containers the access to the
temporary container is more efficient.
A temporary container is automatically opened for writing and neither
{\tt close} nor {\tt commit} or {\tt reset} are allowed on it.

The root container acts like any other
persistent container but it has a fixed identity.
The root object (see above) of the root container plays an even more
special role because this is the only SOS object that can be
accessed ``directly'', i.e. without knowledge of object
references stored in another SOS object.
This object is an instance of class {\tt Directory<sos\_Object>}
(see Section~\ref{sec:The Directory Facility}).
It is named root directory because all (persistently) existing SOS
objects must be reachable from this object.
The root directory can be obtained by calling the static method
{\tt root} of the generic class {\tt Directory}.

Usually applications require several containers to be opened.
In order to avoid deadlocks when two applications try to gain access
to the same set of containers, containers can be opened (and closed)
in sets.
Operations of the type {\tt sos\_Container\_set} provide means for
constructing sets of containers, and for opening, closing,
committing, and resetting these container sets.
These operations perform their actions atomically: either all
containers in the set are opened or none is opened.

A detailed description of the interface is given in
Appendix~\ref{sec:Manual Pages}.
%
%The current implementation maps one container onto one Unix file,
%with the container id as the file name, placed in the directory given
%by an environment variable.

%----------
\subsection{The Aggregate Types}
\label{sec:The Aggregate Types}

To support a convenient usage of the object management system some
useful classes are already predefined in a schema {\tt agg}.
They may be used by an application programmer to build new problem
specific classes for the desired application.
Of course, a designer may define these types by her/his own in a
separate schema only based on the kernel types.

The schema {\tt agg} defines the aggregate types {\tt Array}, 
{\tt Bag}, {\tt List}, {\tt Mapping}, and {\tt Set},
and the auxiliary type {\tt sos\_Cursor}.%
\footnote{as well as some {\tt sos\_Node} types that are only used
          for internal purposes.}
Aggregate types are generic and can be used to build aggregates of
elements of any predefined or user-defined types.

The following paragraphs shortly introduce each predefined aggregate
class.
A complete list of methods for them is given in
Appendix~\ref{sec:Manual Pages}.

%----------
\paragraph*{sos\_Aggregate:}
{\tt sos\_Aggregate} is a superclass of all aggregation classes
({\tt Array}, {\tt Bag}, {\tt Set}, {\tt Mapping}, and {\tt List}).
It defines methods that are useful for all kinds of aggregations,
like for example a method that returns the cardinality of an
aggregation.
Besides, it is the basis for the cursor concept in SOS that enables
a user to scan every instance of an aggregation.
We distinguish between two kinds of aggregations:
{\tt Collection}s and {\tt Association}s.
Instances of subclasses of class {\tt Collection} consist of a
number of single elements, whereas instances of subclasses of class
{\tt Association} consist of a number of pairs.
Therefore, {\tt Mapping}s are a specific form of associations,
and the other predefined aggregate types are specializations of the
class {\tt Association}.

%----------
\paragraph*{Bag:}
A bag is a collection of objects.
The class {\tt Bag} compares to the {\tt Set} class, but offers the
possibility to insert an object more than once.
It provides means for the union, difference, and intersection of
bags and for comparing two instances of class {\tt Bag}.

%----------
\paragraph*{Set:}
In a set, every element must not occur more than once.
Besides this, the properties of class {\tt Set} are similar to
those of class {\tt Bag}.

%----------
\paragraph*{List:}
A list is an ordered, arbitrarily long collection of objects.
Instances of class {\tt List} may be concatenated.

%----------
\paragraph*{Array:}
An array is quite similar to a list but assures efficient access to
its elements.
It is limited in its size at the time of creation.
The class {\tt Array} provides means for manipulating arrays like
registers in programming languages, i.e. there are methods for
shifting and rotating the array contents.

%----------
\paragraph*{Mapping:}
The class {\tt Mapping} provides means for the associative access to 
its elements.
It realizes a function that relates an object of one type (the key
type) to (at most) one object of another type.

%----------
\paragraph*{sos\_Cursor:}
The class {\tt sos\_Cursor} provides means for creating, destroying,
and setting cursors and for sequentially scanning collections in both directions, forward and backward, respectively.
Cursors are especially useful for bags, sets, and mappings, but for
reasons of a unified access to aggregates they may be used for
lists and arrays, too. 

The aggregate classes are part of a class hierarchy which is
illustrated in Figure \ref{fig:AGG}.

\begin{figure}[hbt]
\begin{center}
\
\vspace*{5mm}
\psfig{figure=figures/agg.epsi,height=9cm,width=15cm}
\vspace*{5mm}
\end{center}
\caption{\label{fig:AGG}Inheritance relationships among predefined
         aggregate classes.}
\end{figure}

\pagebreak
%----------
\subsection{The Directory Facility}
\label{sec:The Directory Facility}

The schema {\tt dir} contains the generic class {\tt Directory<sos\_Object>}
which implements a hierarchical {\tt Mapping} from
{\tt sos\_String}s to objects.
It is used to build up a hierarchical structure, by inserting
instances of class {\tt Directory} in other instances of this class.

So, the type {\tt Directory} enables a structuring of the data
that is comparable to the directory hierarchy in file systems.
To support this usage, a {\tt lookup} method is available that accepts a
{\it UNIX-}like pathname, i.e. names of intermediary directory objects
separated by  `{\tt /}' characters. This function returns the corresponding
object, if valid directory names were used.

The class {\tt Directory} is of eminent importance for the usage
of the SOS system, for it enables the access to all objects stored in the
database by providing a static method {\tt root()} which yields
the SOS root object.%
\footnote {see also Section~\ref{sec:The Type sos_Container}}

For a detailed description of class {\tt Directory} refer to
Appendix~\ref{sec:Manual Pages}.
%
%and a process local current working directory.
%
%The current working directory may be set either directly by giving
%a pathname, or alternatively by using the pathname stored in the
%environment variable {\tt SOSDIR}.
%Pathnames are {\it UNIX-}like full paths, i.e. a pathname must start
%with `{\tt /}' and the names of intermediary directory objects are
%separated by `{\tt /}' characters.
%The path {\tt "/"} denotes the SOS root directory, i.e. the root
%object of the root container

%----------
\subsection{The Meta Schema}

The SOS meta schema defines the SOS concepts in terms of its
own data model.
It is used by all methods dealing with already compiled schema
modules for inspecting and manipulating these modules.
That means, it is possible to design schema independent tools which
include the meta schema and are thus enabled to access all objects
by interpreting the appropriate schema module described in terms of
the meta schema.

Each schema module is represented as an instance of class
{\tt sos\_Schema\_module} and all these instances are collected
in one directory ({\tt Directory<sos\_Schema\_module>}). All schema
modules are therefore accessible by this directory.
To obtain this entry point to all meta information,
a static method is provided: {\tt sos\_Schema\_module::schema\_dir()}.

The meta schema itself is a straightforward model of the syntax described in
Section~\ref{sec:The SOS Schema Language}.
It can be found in Appendix~\ref{sec:The Meta Schema}.
Manual pages describing the classes listed there can be found in
Appendix~\ref{sec:Manual Pages}.
